/////////////////////////////////////////////////////////////
// File Name	:	"CGameplayState.cpp"
//
// Author Name	:	Brandon Layton (BL)
//
// Purpose:		:	Basic game world that holds the basic functions of the game
/////////////////////////////////////////////////////////////

#include "../headers/GameplayState.h"
#include "../Systems/Direct3D.h"
#include "../Systems/TextureManager.h"
//#include "Systems/FModManager.h"
#include "../Systems/Input.h"

#include "../headers/Game.h"

//states
//#include "CMainMenuState.h"
//#include "CPauseState.h"
//#include "CCreditsState.h"
//#include "CGameOverState.h"
//#include "CSkillState.h"
//#include "CHUDState.h"
//#include "CLoadingState.h"
//
//#include "CPlayer.h"
//#include "CBullet.h"
//#include "CNPC.h"
//#include "CSpire.h"
//#include "CPortal.h"
#include "../Messaging/MessageSystem.h"
//#include "CCamera.h"

#include <fstream>

using namespace std;

//Constructor
CGameplayState::CGameplayState()
{
	m_pCamera = NULL;

	m_bPaused = false;

	m_bShowDamage = true;
	m_bShowHealthBars = true;

	m_nMapWidth = 0;
	m_nMapHeight = 0;

   // PROTO:
   m_nCurrSelected = -1;

	// Register any events to the client here
	// CEventSystem::GetInstance()->RegisterClient("NAME OF EVENT", this);
}
//Destructor
CGameplayState::~CGameplayState()
{
	// Unregister and events to the client here
	//CEventSystem::GetInstance()->UnregisterClient("NAME OF EVENT", this);
}


CGameplayState * CGameplayState::GetInstance()
{
	static CGameplayState state;

	return &state;
}

void CGameplayState::Enter(void)
{
	m_bPaused = false;
	m_bPanning = false;
	
	m_pD3D	= CDirect3D::GetInstance();
	m_pTM	= CTextureManager::GetInstance();
	//m_pFM	= CFModManager::GetInstance();
	m_pInput= CInput::GetInstance();
	m_pOM	= CObjectManager::GetInstance();
	m_pMS	= CMessageSystem::GetInstance();
	m_pES	= CEventSystem::GetInstance();
	
	//Register Message Proc
	m_pMS->InitMessageSystem(MessageProc);
	
	m_fSecTime = 0.0f;
	
	/*m_nEvilSpireSoundID = m_pFM->LoadSound("resource/sounds/evil1.mp3");
	m_nGoodSpireSoundID = m_pFM->LoadSound("resource/sounds/bomb1.mp3");
	m_nBackgroundMusicID= m_pFM->LoadSound("resource/sounds/warmusic.mp3", FMOD_LOOP_NORMAL, SND_MUSIC);
	m_nEnemyDeathID		= m_pFM->LoadSound("resource/sounds/death.mp3");
	m_nAllyDeathID		= m_pFM->LoadSound("resource/sounds/player_npc_death.mp3");
	m_nAllyAttackID		= m_pFM->LoadSound("resource/sounds/player_npc_basicattk.wav");
	m_nDiffIncreasedID	= m_pFM->LoadSound("resource/sounds/DifficultyIncrease.mp3");*/

	//RegisterEvents that need to be re-registered on enter and not creation
	//CEventSystem::GetInstance()->RegisterClient("NAME OF EVENT", this);

	
	//if(m_bLoadNew)
	{
		//Init Particle System
		//CParticleSystem::GetInstance()->InitSystem(5000, "resource/effects/test.dat");

		//m_pFM->PlaySound(m_nBackgroundMusicID);

		//Create Camera
		m_pCamera = new CCamera(CGame::GetInstance()->GetScreenWidth(), CGame::GetInstance()->GetScreenHeight());
		//m_pCamera->AttachToObject((CBase*)m_pPlayer);
		RECT bounds = {0, 0, m_nMapWidth, m_nMapHeight };
		m_pCamera->SetBounds(bounds);

		m_unGameTime = 0;	
	
		vector<vector2D> points;

		vector2D startPoint(0.0f, 0.0f);
      vector2D endPoint(1.0f, 1.0f);

		vector2D translated = PointToLocalSpace(endPoint, Vector2DNormalize(endPoint - startPoint), Vector2DNormalize(endPoint - startPoint).Perp(), startPoint);

		vector2D midpoint1 = MidPoint(vector2D(), translated);
		midpoint1.fY += m_nMapHeight>>1;
		vector2D midpoint2 = MidPoint(vector2D(), translated);
		midpoint2.fY -= m_nMapHeight>>1;

		midpoint1 = startPoint + VectorToWorldSpace(midpoint1, Vector2DNormalize(endPoint - startPoint), Vector2DNormalize(endPoint - startPoint).Perp());
		midpoint2 = startPoint + VectorToWorldSpace(midpoint2, Vector2DNormalize(endPoint - startPoint), Vector2DNormalize(endPoint - startPoint).Perp());
		endPoint = startPoint + VectorToWorldSpace(translated, Vector2DNormalize(endPoint - startPoint), Vector2DNormalize(endPoint - startPoint).Perp());

		points.push_back(startPoint);
		points.push_back(midpoint1);
		points.push_back(endPoint);
		points.push_back(midpoint2);

		vector<float> times;
		times.push_back(1.0f);
		for(int i = 0; i < 4; i++)
		{
			times.push_back(4.0f);
		}

		
		m_pCamera->MoveAlongPath(points, times);
		m_bPanning = true;
		m_fPanTimer = 0.0f;
	}

	//Add HUD
	//CGame::GetInstance()->AddState(CHUDState::GetInstance());
}

//void CGameplayState::SetUIPositions()
//{
//	m_lfloatingDamages.clear();
//	if(m_pHUD)
//		m_pHUD->SetUIPositions();
//}

bool CGameplayState::Input(void)
{
	if(m_bPaused || m_bLostFocus)
		return true;

	KeyboardDevice * keyboard = (KeyboardDevice*)CInput::GetInstance()->GetDevice(DEV_KEYBOARD);

	if(m_pInput->GetAnyPressed())
	{
		//CEventSystem::GetInstance()->SendEvent("prepfinished");
	}

	/*if(m_pHUD)
		m_pHUD->Input();*/
	return true;
}

void CGameplayState::Update(float dt, bool onTop)
{	
	CGameState::Update(dt, onTop);


	/*if(m_bLostFocus)
	{
		CFModManager::GetInstance()->StopSound(m_nBackgroundMusicID);
	}
	else
	{
		if(CFModManager::GetInstance()->IsSoundPlaying(m_nBackgroundMusicID) == false)
			CFModManager::GetInstance()->PlaySound(m_nBackgroundMusicID);
	}*/
	if(m_bPaused || m_bLostFocus)
		return;

	/*if(!m_bPanning)
	{
		m_fDifficultyTimer -= dt;
		if(m_fDifficultyTimer <= 0.0f)
		{
			m_fDifficultyTimer = m_fDifficultyTime;
			m_fDifficulty *= m_fDifficultyScale;
			CEventSystem::GetInstance()->SendEvent("difficultyincrease");
		}
		
		if(m_fSecTime >= 0.9f)
		{
			m_unGameTime++;
			m_fSecTime = 0.0f;
		}
		if(m_nPrevEnemySpires != m_nEnemyCaptures )
		{	
			m_nPrevEnemySpires = m_nEnemyCaptures;
			m_pFM->PlaySound(m_nEvilSpireSoundID);
		}
		if(m_nPrevPlayerSpires != m_nPlayerCaptures )
		{	
			m_nPrevPlayerSpires = m_nPlayerCaptures;
			m_pFM->PlaySound(m_nGoodSpireSoundID);
		}
	}
	else
	{
		m_fPanTimer += dt;
		if(m_fPanTimer > 18.0f)
		{
			CEventSystem::GetInstance()->SendEvent("prepfinished");
		}
	}*/

	//KeyboardDevice * keyboard = (KeyboardDevice*)CInput::GetInstance()->GetDevice(DEV_KEYBOARD);
	//if(keyboard->KeyDown(DIK_L) || keyboard->KeyPressed(DIK_K))
	{
		m_pOM->UpdateObjects(dt, onTop);
		//CParticleSystem::GetInstance()->Update(dt);

		m_pOM->CheckCollision();

	

		/*for(list<FloatText>::iterator i = m_lfloatingDamages.begin(); i != m_lfloatingDamages.end();)
		{
			i->deltaTime += dt;
			i->offSetY -= (unsigned int)(100 * dt);
			if(i->deltaTime >= 2.0f)
			{
				i = m_lfloatingDamages.erase(i);			
			}
			else
			{
				i++;
			}
		}*/
	}

	m_pCamera->Update(dt);

	m_fSecTime += dt;

	/*if(m_pHUD)
		m_pHUD->Update(dt, onTop);*/
} 

void CGameplayState::Render(vector2D & vCamera)
{
	//Render Objects
	m_pOM->RenderObjects(m_pCamera->GetPosition());
	//CParticleSystem::GetInstance()->Render(m_pCamera->GetPosition());
	vCamera = m_pCamera->GetPosition();

	CDirect3D::GetInstance()->SpriteEnd();
	CDirect3D::GetInstance()->SpriteBegin();
	//Render Healthbars
	vector<CBase*> npcs = CObjectManager::GetInstance()->GetObjectsByType(OBJ_NPC);
	
	/*for(vector<CBase*>::iterator npcItt = npcs.begin(); npcItt != npcs.end(); ++npcItt)
	{
		CNPC * npc = (CNPC*)(*npcItt);
		RECT currentHealth = npc->GetHealthBar();
		float interpolHealth = (npc->GetCurrentHealth() / npc->GetMaxHealth()) * 48.0f;
		if(interpolHealth > 48.0f)
			interpolHealth = 48.0f;
		currentHealth.left = (int)npc->GetPosX() - (((int)npc->GetAnchorPoint().fX)>>1);
		currentHealth.top = (int)npc->GetPosY() - (int)npc->GetAnchorPoint().fY;
		currentHealth.bottom = currentHealth.top + 10;
		currentHealth.right = (int)(currentHealth.left + interpolHealth);

		currentHealth.left -= (int)vCamera.fX;
		currentHealth.top -= (int)vCamera.fY;
		currentHealth.right -= (int)vCamera.fX;
		currentHealth.bottom -= (int)vCamera.fY;
		
		if(npc->GetIsEnemy())
			CDirect3D::GetInstance()->DrawRect(currentHealth, 255, 0, 0);
		else
			CDirect3D::GetInstance()->DrawRect(currentHealth, 0, 255, 0);
	}*/
	CDirect3D::GetInstance()->SpriteEnd();
	CDirect3D::GetInstance()->SpriteBegin();

	CBitmapFont* tempBMF = CGame::GetInstance()->GetFont();
	/*if(m_bShowDamage)
	{
		for(list<FloatText>::iterator i = m_lfloatingDamages.begin(); i != m_lfloatingDamages.end(); ++i)
		{
			if(i->damage != 0)
			{
				char nums[64];
				DWORD color = -1;
				if(i->damage > 0.0f)
					color = RED;
				else
					color = GREEN;
				sprintf_s(nums, "%d", abs(i->damage));



				tempBMF->DrawText(nums, i->locX - vCamera.fX, i->locY - vCamera.fY + i->offSetY, 1000, 1.0f, color);
			}
			else
			{
				tempBMF->DrawText((char*)i->text.c_str(), i->locX - vCamera.fX - 100, i->locY -vCamera.fY + i->offSetY, 1000, 1.2f, BLUE);
			}
		}
	}*/

	float tempScale = 1.0f; //m_pHUD->GetScaleY();
	if(m_bPanning)
	{
		tempBMF->DrawText("PRESS ANY KEY TO SKIP", float(CGame::GetInstance()->GetScreenWidth()>>1) - 200.0f, 60.0f * tempScale);
	}

// Show the Bounds and Paths for debugging
//#if _DEBUG
//	vector<CWall*> walls = CObjectManager::GetInstance()->GetWalls();
//
//	for(vector<CWall*>::iterator itt = walls.begin(); itt != walls.end(); ++itt)
//	{
//		(*itt)->Render(vCamera);
//	}
//
//	vector<CPath*> paths = CObjectManager::GetInstance()->GetPaths();
//	for(vector<CPath*>::iterator itt = paths.begin(); itt != paths.end(); ++itt)
//	{
//		(*itt)->Render(vCamera);
//	}
//#endif

	/*if(m_pHUD && m_bPaused == false)
		m_pHUD->Render(vCamera);*/
}

void CGameplayState::Exit(void)
{
	/*m_pFM->StopSound(m_nBackgroundMusicID);
	m_pFM->UnloadSound(m_nBackgroundMusicID);
	m_pFM->UnloadSound(m_nEvilSpireSoundID);
	m_pFM->UnloadSound(m_nGoodSpireSoundID);
	m_pFM->UnloadSound(m_nEnemyDeathID);
	m_pFM->UnloadSound(m_nAllyDeathID);
	m_pFM->UnloadSound(m_nAllyAttackID);*/

	CEventSystem::GetInstance()->UnregisterClient("spirecaptured", this);
	CEventSystem::GetInstance()->UnregisterClient("difficultyincrease", this);
	CEventSystem::GetInstance()->UnregisterClient("prepfinished", this);

	//m_lfloatingDamages.clear();
	CEventSystem::GetInstance()->ClearEvents();
	SAFE_DELETE(m_pCamera);
	//CParticleSystem::GetInstance()->ShutdownSystem();
	m_pOM->RemoveAllObjects();

	//SetLoadNew(true);

	/*if(m_pHUD)
	{
		m_pHUD->Exit();
		delete m_pHUD;
		m_pHUD = NULL;
	}*/
}


void MessageProc(CBaseMessage * pMsg)
{
	if(pMsg != NULL)
	{
		CGameplayState * state = CGameplayState::GetInstance();
		state->GameplayMessageProc(pMsg);
	}
}

void CGameplayState::GameplayMessageProc(CBaseMessage *pMsg)
{
	if(pMsg->GetMsgID() == MSG_DESTROY_OBJECT)
	{
		CDestroyObjectMessage * msg = (CDestroyObjectMessage*)pMsg;
		CObjectManager::GetInstance()->RemoveObject(msg->GetBaseObject(), 2);
	}
}

struct tGameObject
{
	char				imagePath[MAX_PATH];
	RECT				drawRect;
	RECTF				collisionRect;
	unsigned int		ID;
	int					layer;
	string				name;
};

/*void CGameplayState::LoadLevelFromFile(char * fileName)
{
	ifstream stream(fileName, ios_base::binary);

	char resourcePath[] = "resource/graphics/";
	if(stream.is_open())
	{
		map<string, tGameObject> definedObjects;
		int tempNum;
		stream.read((char *)&m_nMapWidth, sizeof(int));				//Screen Width
		stream.read((char *)&m_nMapHeight, sizeof(int));				//Screen Height

		int objCount;
		stream.read((char *)&objCount, sizeof(int));			//Obj Count

		for(int i = 0; i < objCount; i++)
		{
			tGameObject obj;
			stream.read((char*)&tempNum, sizeof(int));			//Path Length
			char path[MAX_PATH];
			char p[MAX_PATH];
			stream.read(path, tempNum);							//Path
			path[tempNum] = '\0';			
			strcpy_s(obj.imagePath, strlen(resourcePath) + 1, resourcePath);
			strcat_s(obj.imagePath, path);			
			stream.read((char*)&tempNum, sizeof(int));			//Obj Name Length
			stream.read(p, tempNum);							//Obj Name
			p[tempNum] = '\0';
			obj.name = p;

			stream.read((char*)&tempNum, sizeof(int));			//Draw top
			obj.drawRect.left	=	(LONG)tempNum;
			stream.read((char*)&tempNum, sizeof(int));			//Draw left
			obj.drawRect.top	=	(LONG)tempNum;
			stream.read((char*)&tempNum, sizeof(int));			//Draw bottom
			obj.drawRect.right =	(LONG)tempNum;
			stream.read((char*)&tempNum, sizeof(int));			//Draw right
			obj.drawRect.bottom	=	(LONG)tempNum;

			stream.read((char*)&tempNum, sizeof(int));			//Collision top
			obj.collisionRect.left		= (float)tempNum - obj.drawRect.left;
			stream.read((char*)&tempNum, sizeof(int));			//Collision left
			obj.collisionRect.top		= (float)tempNum - obj.drawRect.top;
			stream.read((char*)&tempNum, sizeof(int));			//Collision bottom
			obj.collisionRect.right		= (float)tempNum - obj.drawRect.left;
			stream.read((char*)&tempNum, sizeof(int));			//Collision right
			obj.collisionRect.bottom	= (float)tempNum - obj.drawRect.top;

			stream.read((char*)&obj.ID, sizeof(unsigned int));	//ID

			definedObjects[obj.name] = obj;

		}

		stream.read((char*)&objCount, sizeof(int));
		for(int i = 0; i < objCount; i++)
		{
			unsigned int id;
			int posX;
			int posY;
			unsigned int eventActor;
			unsigned int eventTarget;
			char eventName[60];
			int layer;
			int type;
			bool enemy;
			char name[255];
			
			char spawntype[255];
			vector<string> playerspawntypes;
			vector<string> enemyspawntypes;
			int  numnpcs = 0;
			string strname;
			int numspawn = 0;
			vector<Connection> connections;

			stream.read((char*)&layer, sizeof(int));				//Layer
			stream.read((char*)&id, sizeof(unsigned int));			//ID
			stream.read((char*)&posX, sizeof(int));					//Pos X
			stream.read((char*)&posY, sizeof(int));					//Pos Y
			stream.read((char*)&eventActor, sizeof(unsigned int));	//Event Actor
			stream.read((char*)&tempNum, sizeof(int));				
			stream.read((char*)&eventName, tempNum);				//Event Name
			eventName[tempNum] = '\0';
			stream.read((char*)&tempNum, sizeof(int));			//Obj Name Length
			stream.read(name, tempNum);							//Obj Name
			name[tempNum] = '\0';
			strname = name;
			stream.read((char*)&eventTarget, sizeof(unsigned int));	//Event Target
			stream.read((char*)&type, sizeof(int));					//Type
			stream.read((char*)&tempNum, sizeof(int));			    //Number of connections
			for(int j = 0; j < tempNum; j++)
			{
				Connection c;
				stream.read((char*)&c.type, sizeof(int));
				stream.read((char*)&c.connectedTo, sizeof(unsigned int));
				connections.push_back(c);

			}
			stream.read((char*)&numspawn, sizeof(int));
			for(int m = 0; m < numspawn; m++)
			{
				stream.read((char*)&tempNum, sizeof(int));
				stream.read((char*)&spawntype, tempNum);
				spawntype[tempNum] = '\0';
				playerspawntypes.push_back(spawntype);
			}

			stream.read((char*)&numspawn, sizeof(int));
			for(int m = 0; m < numspawn; m++)
			{
				stream.read((char*)&tempNum, sizeof(int));
				stream.read(spawntype, tempNum);
				spawntype[tempNum] = '\0';
				enemyspawntypes.push_back(spawntype);
			}

			
			stream.read((char*)&enemy, sizeof(bool));
			
			tGameObject obj = definedObjects[strname];
			obj.layer = layer;
			
			
			switch(type)
			{
			case 0://Tile
				{
				CBase * tile = new CBase();				
				
				tile->SetImageID(obj.imagePath);
				tile->SetPosition(vector2D((float)posX, (float)posY));
				tile->SetCollisionRect(obj.collisionRect);
				tile->SetImageRect(obj.drawRect);
				tile->SetWidth(obj.drawRect.right - obj.drawRect.left);
				tile->SetHeight(obj.drawRect.bottom - obj.drawRect.top);
				tile->SetID(id);
				if(obj.layer == 2)
					tile->SetIsObstacle(true);
				CObjectManager::GetInstance()->AddObject(tile, obj.layer);
				tile->Release();

				break;
				}
			case 1: //spire
				{
				CSpire * spire = new CSpire();
				spire->SetImageID(obj.imagePath);
				spire->SetWidth(obj.drawRect.right - obj.drawRect.left);
				spire->SetHeight(obj.drawRect.bottom - obj.drawRect.top);
				spire->SetAnchorPoint(vector2D());
				spire->SetPosition(vector2D((float)posX, (float)posY));
				obj.collisionRect.left = -40.0f;
				obj.collisionRect.right = 40.0f;
				obj.collisionRect.top = -40.0f;
				obj.collisionRect.bottom = 40.0f;
				spire->SetCollisionRect(obj.collisionRect);
				spire->SetImageRect(obj.drawRect);
				spire->SetFocusPoint(vector2D(0, -100));
				spire->SetID(id);
				spire->SetPlayerSpawnType(playerspawntypes);
				spire->SetEnemySpawnType(enemyspawntypes);
				
				
				for(vector<Connection>::iterator itt = connections.begin(); itt != connections.end(); itt++)
				{
					spire->AddConnection((*itt).type, (*itt).connectedTo);
				}

				m_pOM->AddObject(spire, 2);
				spire->Release();
				m_nTotalSpires++;
				break;
				}
			case 2: //portal
				{
				CPortal * portal = new CPortal();
				portal->SetWidth(166);
				portal->SetHeight(166);
				portal->SetAnchorPoint(vector2D());
				portal->SetPosition(vector2D((float)posX, (float)posY));
				portal->SetIsEnemy(enemy);
				portal->SetImageID(obj.imagePath);
				portal->SetWidth(obj.drawRect.right - obj.drawRect.left);
				portal->SetHeight(obj.drawRect.bottom - obj.drawRect.top);
				portal->SetCollisionRect(obj.collisionRect);
				portal->SetImageRect(obj.drawRect);
				portal->SetID(id);
				portal->SetPlayerSpawnType(playerspawntypes);
				portal->SetEnemySpawnType(enemyspawntypes);
				portal->SetNumNPCToSpawn(numnpcs);

				if(!enemy)
					m_pPortal = portal;
				else
					m_pEPortal = portal;

				m_pOM->AddObject(portal, 2);
				portal->Release();
				break;
				}
			}

		}

		int numWalls;
		stream.read((char*)&numWalls, sizeof(int));

		for(int i = 0; i < numWalls; i++)
		{
			float p1x;
			float p1y;
			float p2x;
			float p2y;

			stream.read((char*)&p1x, sizeof(float));
			stream.read((char*)&p1y, sizeof(float));
			stream.read((char*)&p2x, sizeof(float));
			stream.read((char*)&p2y, sizeof(float));

			CObjectManager::GetInstance()->AddWall(new CWall(vector2D(p1x, p1y), vector2D(p2x, p2y)));
		}

		int numPaths;
		stream.read((char*)&numPaths, sizeof(int));

		for(int i = 0; i < numPaths; i++)
		{
			int numWaypoints;
			stream.read((char*)&numWaypoints, sizeof(int));
			CPath * path = new CPath();
			for(int j = 0; j < numWaypoints; j++)
			{
				int x;
				int y;

				stream.read((char*)&x, sizeof(int));
				stream.read((char*)&y, sizeof(int));

				path->AddWaypoint(vector2D((float)x, (float)y));
			}

			CObjectManager::GetInstance()->AddPath(path);
		}

		definedObjects.clear();

		stream.close();
	}

}*/



bool CGameplayState::HandleEvent(CEvent * pEvent)
{
	if(pEvent->GetEventID() == "prepfinished")
	{
		if(m_bPanning)
		{
			m_bPanning = false;
			//m_pCamera->AttachToObject(m_pPlayer);
			m_fPanTimer = 0.0f;
		}
	}
	return true;

}

void CGameplayState::AddFloatDamage(float fDamage, float locX, float locY, string sztext)
{
	FloatText tFT;
	tFT.text = sztext;
	tFT.damage = (int)fDamage;
	tFT.deltaTime = 0.0f;
	tFT.offSetY = -48;
	tFT.locX = locX;
	tFT.locY = locY;
	//m_lfloatingDamages.push_back(tFT);

}

void CGameplayState::SetupGrid(int nFormat)
{
   if(nFormat == NONE)
   {
      // TODO: For now send an error that the format is not specified
      MessageBox(0, "Grid Format Error", "No Grid Format Specified. GameplayState.cpp.  Line 696.", MB_OK);
   }
   else if(nFormat == SQUARE)
   {
      // TODO: implement
   }
   else if(nFormat == HEX)
   {
      float positionX = 0.0f;
      float positionY = 0.0f;
      float side = 24.0f;
      int row = 0;

      while(positionY <= (float)CGame::GetInstance()->GetScreenHeight() + side)
      {
         // add an extra width to the start if we're on an even row
         if(row % 2 != 0)
            positionX += sqrt((side * side) - ((side / 2.0f) * (side / 2.0f)));

         while(positionX <= (float)CGame::GetInstance()->GetScreenWidth() + side)
         {
            //CDirect3D::GetInstance()->DrawHex(vector2D(positionX, positionY), RED, side);
            // Create a Hexagon and add it to the grid
            GRID_LOC<HEX_SHAPE> location(HEX_SHAPE(positionX, positionY, side), vector2D(positionX, positionY));

            m_vHexGrid.push_back(location);

            positionX += 2 * sqrt((side * side) - ((side / 2.0f) * (side / 2.0f)));
         }

         positionX = 0.0f;
         positionY += 1.5f * side;
         row++;
      }
   }
}

/*bool CGameplayState::SaveGame(int saveSlot)
{
	char buffer[MAX_PATH];
	sprintf_s(buffer, MAX_PATH, "Saved Games/saveslot%d.hbs", saveSlot);

	ofstream stream(buffer, ios_base::binary | ios_base::trunc);

	if(stream.is_open())
	{
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Standard Header for save file load in save slot data
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////
		char levelName[MAX_PATH];
		strcpy_s(levelName, MAX_PATH, m_szLevelFilePath);
		stream.write((char*)levelName, MAX_PATH);					//Record the Level file used
		stream.write((char*)&m_unGameTime, sizeof(unsigned int));	//Record the game time
		int playerint = GetPlayer()->GetLevel();
		stream.write((char*)&playerint, sizeof(int));				//Record the player Level		
		
		vector<CBase*> npcs = CObjectManager::GetInstance()->GetObjectsByType(OBJ_NPC);	//Get NPCs from Object Manager
		int size = (int)npcs.size();
		int tempenemies = 0;
		for(int i = 0; i < size; i++)
		{
			CNPC* npc = (CNPC*)npcs[i];
				
			if(npc->GetIsEnemy())					//Check if the npc is an enemy
				tempenemies++;						//add to the enemies amount
		}
		stream.write((char*)&tempenemies, sizeof(int));				//Record the number of enemies
		tempenemies = ((int)size - tempenemies);					//Use the temp enemies for the nuber of allies
		stream.write((char*)&tempenemies, sizeof(int));				//Record the number of allies		
		
		vector<CBase*> portals = CObjectManager::GetInstance()->GetObjectsByType(OBJ_PORTAL); //Get Portals from Object Manager
		size = (int)portals.size();
		float temphealth = 0.0f;
		for(int i = 0; i < size; i++)
		{
			CPortal* portal = (CPortal*)portals[i];

			if(!portal->GetIsEnemy())				//Check if the portal is an enemy
				temphealth = portal->GetHealth();	//set the temp health to this portals health
		}
		stream.write((char*)&temphealth, sizeof(float));			//Record the health of the players portal

		vector<CBase*> spires = CObjectManager::GetInstance()->GetObjectsByType(OBJ_SPIRE); //Get Spires from Object Manager
		size = (int)spires.size();
		int tempinfluence = 0;
		stream.write((char*)&size, sizeof(int));
		for(int i = 0; i < size; i++)
		{
			CSpire* spire = (CSpire*)spires[i];

			if(spire->GetInfluence() >= 99.0f)		//Check if the player has influence on the spire
				tempinfluence++;					//add the spire to the spires the player controls
		}
		stream.write((char*)&tempinfluence, sizeof(int));				//Record spires the player controls
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// End of Standard Header
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		
		//Write other player stats
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		unsigned int tempID = GetPlayer()->GetID();
		stream.write((char*)&tempID, sizeof(int));

		int tempint = GetPlayer()->GetClassType();
		stream.write((char*)&tempint, sizeof(int));

		vector2D tempvec = GetPlayer()->GetPosition();
		stream.write((char*)&tempvec, sizeof(vector2D));
		
		float playerfloat = GetPlayer()->GetCurrentHealth();
		stream.write((char*)&playerfloat, sizeof(float));			//Record the player's current health

		playerfloat = GetPlayer()->GetExperience();
		stream.write((char*)&playerfloat, sizeof(float));			//Record the experience needed until the next level
		
		playerint = GetPlayer()->GetSkill1Lvl();
		stream.write((char*)&playerint, sizeof(int));				//Record the player skill1 level
		playerint = GetPlayer()->GetSkill1Lvl();
		stream.write((char*)&playerint, sizeof(int));				//Record the player skill2 level
		playerint = GetPlayer()->GetSkill1Lvl();
		stream.write((char*)&playerint, sizeof(int));				//Record the player skill3 level

		vector<bool> bools = GetPlayer()->GetPassiveSkills();
		size = (int)bools.size();
		stream.write((char*)&size, sizeof(int));
		for(int i = 0; i < size; i++)
		{
			stream.write((char*)&bools[i], sizeof(bool));			//Record the players passive skills
		}

		bool tempbool;
		string tempstring;
		float tempfloat;
		//Write npc stats
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		npcs = CObjectManager::GetInstance()->GetObjectsByType(OBJ_NPC);
		size = (int)npcs.size();
		stream.write((char*)&size, sizeof(int));
		for(int i = 0; i < size; i++)
		{
			CNPC* npc = (CNPC*)npcs[i];

			tempID = npc->GetID();
			stream.write((char*)&tempID, sizeof(unsigned int));		//Record the ID of the npc

			tempstring = npc->GetTypeName();
			stream.write((char*)&tempstring, sizeof(string));		//Record the typename of the npc

			tempfloat = npc->GetCurrentHealth();
			stream.write((char*)&tempfloat, sizeof(float));			//Record the damage the enemy has taken

			tempvec = npc->GetPosition();
			stream.write((char*)&tempvec, sizeof(vector2D));		//Record the position of the npc
		}

		//Write portal stats
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		portals = CObjectManager::GetInstance()->GetObjectsByType(OBJ_PORTAL);
		size = (int)portals.size();		
		for(int i = 0; i < size; i++)
		{
			CPortal* portal = (CPortal*)portals[i];

			tempID = portal->GetID();
			stream.write((char*)&tempID, sizeof(unsigned int));		//Record the portals ID

			tempfloat = portal->GetHealth();
			stream.write((char*)&tempfloat, sizeof(float));			//Record the health of the portal

			tempbool = portal->GetIsEnemy();
			stream.write((char*)&tempbool, sizeof(bool));			//Record whether the portal is an enemy

			tempvec = portal->GetPosition();
			stream.write((char*)&tempvec, sizeof(vector2D));		//Record the position of the portal
		}

		//Write spire stats
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		spires = CObjectManager::GetInstance()->GetObjectsByType(OBJ_SPIRE);
		size = (int)spires.size();
		stream.write((char*)&size, sizeof(int));
		for(int i = 0; i < size; i++)
		{
			CSpire* spire = (CSpire*)spires[i];

			tempID = spire->GetID();
			stream.write((char*)&tempID, sizeof(unsigned int));		//Record the ID of the spire

			tempfloat = spire->GetInfluence();
			stream.write((char*)&tempfloat, sizeof(float));			//Record the influence of the spire
		}

		//Write bullets on screen
		//CBase * pOwner, int imageID, float damage, bool isEnemy, vector2D velocity, vector2D position, bool useParticle, 
		//string & particleType, float fTravelDistance);
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		//vector<CBase*> bullets = CObjectManager::GetInstance()->GetObjectsByType(OBJ_BULLET);
		//size = (int)bullets.size();
		//stream.write((char*)&size, sizeof(int));
		//for(int i = 0; i < size; i++)
		//{
		//	CBullet* bullet = (CBullet*)bullets[i];

		//	tempID = bullet->GetOwner()->GetID();
		//	stream.write((char*)&tempID, sizeof(int));				//Record the ID of the bullet's owner

		//	tempfloat = bullet->GetDamage();
		//	stream.write((char*)&tempfloat, sizeof(float));			//Record the damage of the bullet

		//	tempbool = bullet->GetIsEnemy();
		//	stream.write((char*)&tempbool, sizeof(bool));			//Record whether the bullet is an enemy

		//	tempvec = bullet->GetVelocity();
		//	stream.write((char*)&tempvec, sizeof(vector2D));		//Record the velocity of the bullet

		//	tempvec = bullet->GetPosition();
		//	stream.write((char*)&tempvec, sizeof(vector2D));		//Record the position of the bullet

		//	tempbool = bullet->GetIsSpell();
		//	stream.write((char*)&tempbool, sizeof(bool));			//Record whether the bullet has particles

		//	tempstring = bullet->GetParticleType();
		//	stream.write((char*)&tempstring, sizeof(string));		//Record the particle type

		//	tempfloat = bullet->GetTotalDistance();
		//	stream.write((char*)&tempfloat, sizeof(float));			//Record the distance left for the bullet to travel
		//}
	}
	else
	{
		return false;
	}

	stream.close();
	return true;
}

bool CGameplayState::LoadGame(int loadSlot)
{
	char buffer[MAX_PATH];
	sprintf_s(buffer, MAX_PATH, "Saved Games/saveslot%d.hbs", loadSlot);

	ifstream stream(buffer, ios_base::binary);

	if(stream.is_open())
	{
		//Init Particle System
		CParticleSystem::GetInstance()->InitSystem(5000, "resource/effects/test.dat");
		
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Standard Header for save file load in save slot data
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////
		char levelName[MAX_PATH];
		stream.read((char*)levelName, MAX_PATH);					//Read the Level file used
		LoadLevelFromFile(levelName);								//Load Map

		stream.read((char*)&m_unGameTime, sizeof(unsigned int));	//Read the game time
	
		
		m_pPlayer = new CPlayer();									//Create Player
		int playerint;
		stream.read((char*)&playerint, sizeof(int));				//Read the player Level		
		GetPlayer()->SetLevel(playerint);

		int size;
		
		//Do not need this for loading game toss out
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		int tempenemies;
		stream.read((char*)&tempenemies, sizeof(int));				//Read the number of enemies
		stream.read((char*)&tempenemies, sizeof(int));				//Read the number of allies		
		float temphealth = 0.0f;
		stream.read((char*)&temphealth, sizeof(float));				//Read the health of the players portal
		int tempinfluence = 0;
		stream.read((char*)&size, sizeof(int));
		stream.read((char*)&tempinfluence, sizeof(int));			//Read spires the player controls
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// End of Standard Header
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		CNPC::LoadNPCTypesFromFile("resource/NPC Files/test.ngf");
		
		//Read other player stats
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		unsigned int tempID;
		stream.read((char*)&tempID, sizeof(int));					//Read in the player's ID					
		GetPlayer()->SetID(tempID);

		stream.read((char*)&playerint, sizeof(int));
		m_nPlayerClass = (ClassType)playerint;
		m_pPlayer->SetClassType(m_nPlayerClass);

		vector2D tempvec;
		stream.read((char*)&tempvec, sizeof(vector2D));
		m_pPlayer->SetPosition(tempvec);

		float playerfloat;
		stream.read((char*)&playerfloat, sizeof(float));			//Read in player's current health
		GetPlayer()->SetDamage(GetPlayer()->GetCurrentHealth() - playerfloat);

		stream.read((char*)&playerfloat, sizeof(float));			//Read in experience needed until the next level
		GetPlayer()->SetCurrentXP(playerfloat);
		
		stream.read((char*)&playerint, sizeof(int));				//Read in player skill1 level
		GetPlayer()->SetSkill1Lvl(playerint);
		stream.read((char*)&playerint, sizeof(int));				//Read in player skill2 level
		GetPlayer()->SetSkill1Lvl(playerint);
		stream.read((char*)&playerint, sizeof(int));				//Read in player skill3 level
		GetPlayer()->SetSkill1Lvl(playerint);

		vector<bool> bools;
		bool tempbool = false;
		stream.read((char*)&size, sizeof(int));
		for(int i = 0; i < size; i++)
		{
			stream.read((char*)&tempbool, sizeof(bool));			//Read in players passive skills
			bools.push_back(tempbool);
		}
		GetPlayer()->SetPassiveSkills(bools);
		
		string tempstring;
		float tempfloat;
		//Read npc stats
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		stream.read((char*)&size, sizeof(int));
		for(int i = 0; i < size; i++)
		{
			stream.read((char*)&tempID, sizeof(unsigned int));
			stream.read((char*)&tempstring, sizeof(string));
			stream.read((char*)&tempfloat, sizeof(float));
			stream.read((char*)&tempvec, sizeof(vector2D));

			CMessageSystem::GetInstance()->SendMsg(new CCreateNPCMessage(tempstring, tempvec, tempfloat, true, tempID));
		}

		//Read portal stats
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		vector<CBase*> portals = CObjectManager::GetInstance()->GetObjectsByType(OBJ_PORTAL);
		//stream.read((char*)&size, sizeof(int));
		for(int i = 0; i < (int)portals.size(); i++)
		{
			CPortal* portal = (CPortal*)portals[i];

			stream.read((char*)&tempID, sizeof(unsigned int));
			portal->SetID(tempID);

			stream.read((char*)&tempfloat, sizeof(float));
			portal->SetHealth(tempfloat);

			stream.read((char*)&tempbool, sizeof(bool));
			portal->SetIsEnemy(tempbool);

			stream.read((char*)&tempvec, sizeof(vector2D));
			portal->SetPosition(tempvec);
		}

		//Read spire stats
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		vector<CBase*> spires = CObjectManager::GetInstance()->GetObjectsByType(OBJ_SPIRE);
		stream.read((char*)&size, sizeof(int));
		for(int i = 0; i < (int)spires.size(); i++)
		{
			CSpire* spire = (CSpire*)spires[i];

			stream.read((char*)&tempID, sizeof(unsigned int));
			spire->SetID(tempID);

			stream.read((char*)&tempfloat, sizeof(float));
			spire->SetInfluence(tempfloat);
		}

		//Read bullets on screen
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/*	vector<CBase*> objects = CObjectManager::GetInstance()->GetObjectsByLayer(2);
		stream.read((char*)&size, sizeof(int));
		for(int i = 0; i < size; i++)
		{
			CBullet* bullet = new CBullet();

			stream.read((char*)&tempID, sizeof(int));
			for(int j = 0; j < (int)objects.size(); j++)
			{
				if(objects[i]->GetID() == tempID)
					bullet->SetOwner(objects[i]);
			}

			stream.read((char*)&tempfloat, sizeof(float));
			bullet->SetDamage(tempfloat);

			stream.read((char*)&tempbool, sizeof(bool));
			bullet->SetIsEnemy(tempbool);

			stream.read((char*)&tempvec, sizeof(vector2D));
			bullet->SetVelocity(tempvec);

			stream.read((char*)&tempvec, sizeof(vector2D));
			bullet->SetPosition(tempvec);

			stream.read((char*)&tempbool, sizeof(bool));
			bullet->SetUseParticle(tempbool);

			stream.read((char*)&tempstring, sizeof(string));
			bullet->SetParticleType(tempstring);

			stream.read((char*)&tempfloat, sizeof(float));
			bullet->SetTotalDistance(tempfloat);

			CCharacter* tempChar = (CCharacter*)bullet->GetOwner();
			CMessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(bullet->GetOwner(), tempChar->GetBulletImageID(), bullet->GetDamage(), bullet->GetIsEnemy(),
				bullet->GetVelocity(), bullet->GetPosition(), bullet->GetIsSpell(), bullet->GetParticleType(), bullet->GetTotalDistance()));
		}/*
	}
	else
	{
		return false;
	}

	stream.close();

	m_pFM->PlaySound(m_nBackgroundMusicID);

	m_pOM->AddObject(m_pPlayer, 2);
	m_bPlayerWon = false;

	//Create Camera
	m_pCamera = new CCamera(CGame::GetInstance()->GetScreenWidth(), CGame::GetInstance()->GetScreenHeight());
	m_pCamera->AttachToObject(m_pPlayer);
	RECT bounds = {0, 0, m_nMapWidth, m_nMapHeight };
	m_pCamera->SetBounds(bounds);

	return true;
}*/
